import pandas as pd
from openai import OpenAI
from sklearn.metrics import accuracy_score
import ollama
from pandasai.llm.local_llm import LocalLLM
from pandasai import SmartDataframe
import numpy as np
import pandas as pd
from warnings import simplefilter
import streamlit as lit
from pandasai.llm import OpenAI as ai

simplefilter(action="ignore", category=pd.errors.PerformanceWarning)
simplefilter(action="ignore", category=FutureWarning)
#ignore ValueError
simplefilter(action="ignore", category=ValueError)
API_key = 'apikey'
client = OpenAI(api_key=API_key)

# question = input('Enter the question you want to ask the model: ')


def openai_result(query, df):
    model = ai(API_key)

    sdf = SmartDataframe(df = df, config={"llm":model})
    try:
        response = sdf.chat(query+'If graphing, you must return a sentence: Graphing completed')
        return response
    except:
        return 'FAILED'
    


def local_llm_result(model,query,df):
    sdf = SmartDataframe(df=df, config={"llm": model,"save_logs": True, "conversational": True,"verbose":True})
    
    result = sdf.chat(query+'If graphing, you must return a sentence: Graphing completed')
    return result

def truth_value(df,query):
    result = eval(query)
    return result


if __name__ == '__main__':
    # initializations
    filename = 'data/cleaned_data.csv'
    df = pd.read_csv(filename, low_memory=False)

    # column_ids = [84, 101, 114, 166, 183, 187, 188, 190, 194, 199, 204, 206, 276]
    # column_names = df.columns[column_ids]
    # for col_name in column_names:
    #     if col_name in df.columns:
    #         df[col_name] = df[col_name].astype(str).replace('nan', 'NULL')
    
    


    # query construction
    # mode = input('Enter running mode: 0 is from file, 1 is manual')



    # print(result_llm)
    query_to_openai = 'I want you to be the prompt engingeer and edit the prompt I will give you based on the column I give you. Can you replace the related content with the exact column name. To be remind about only return the edited content don\'t say something like here\'s the edited prompt, I only want the result. I want the prompt to be accuracy as well and envolve with all the necessary key words, try to use minimal calls to the columns. When calling column names put a quatation mark around the column name. Also you must not generate any hypotetic data not even for demonstration purpose.'
    
    # query_to_openai += 'filepath:data/cleaned_data.csv'
    column_names = df.columns
    column_values = ''
    prohibited = ['CrashId']
    for col_name in df.columns:
        if col_name not in prohibited:
            column_values += col_name + ':' + ', '.join(map(str, df[col_name].unique())) + '\n'

    questions = []
    with open('questions.txt', 'r') as f:
        questions = f.readlines()
    c = 0
    for question in questions:
        query_to_openai += 'Column names:' + ', '.join(column_names)

        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {
                    "role": "system",
                    "content": query_to_openai
                },
                {
                    "role": "user",
                    "content": question 
                }
            ],
            temperature=0.7,
            max_tokens=1024,
            top_p=1
        )

        message = response.choices[0].message.content
        print("Edited prompt:", message)
        pre_prompting = 'I want you to generate code, CODE ONLY! The code must not contain comments. use pandas functions as possible, Do not define a function put everything down. Directly call on it. A dataframe called \'dfs\' is already defined, all the data you need is in there, do not try to call os or access other files.'
        # pre_prompting += ', '.join(column_names)
        pre_prompting = 'Do not generate hypotetic data. Assume data is prepared already'
        ignore_prompt = 'Ignore What I say from this point'
        message_to_execute = pre_prompting + message
        question = pre_prompting + question

        # message += 'the data file name is'+filename
        # pre_prompt = 'I want you to repeat what I say:'
        # message = pre_prompt + message

        ### The result generation Factory:
        try:
            model = LocalLLM(api_base="http://localhost:11434/v1", model="llama3.1:latest")
            llama_result = local_llm_result(model,message_to_execute,df)
            if 'Unfortunately' in llama_result:
                llama_result = 'FAILED'
        except:
            llama_result = 'FAILED'
        try:
            model = LocalLLM(api_base="http://localhost:11434/v1", model="deepseek-coder-v2:latest")
            deepseek_result = local_llm_result(model,message_to_execute,df)
            if 'Unfortunately' in deepseek_result:
                deepseek_result = 'FAILED'
        except:
            deepseek_result = 'FAILED'
        try:
            model = LocalLLM(api_base="http://localhost:11434/v1", model="starcoder2:latest")
            starcoder_result = local_llm_result(model,message_to_execute,df)
            if 'Unfortunately' in starcoder_result:
                starcoder_result = 'FAILED'
        except:
            starcoder_result = 'FAILED'
        try:
            model = LocalLLM(api_base="http://localhost:11434/v1", model="gemma2:27b")
            gemma_result = local_llm_result(model,message_to_execute,df)
            if 'Unfortunately' in gemma_result:
                gemma_result = 'FAILED'
        except:
            gemma_result = 'FAILED'
        try:
            chatgpt_result = openai_result(message_to_execute,df)
            if 'Unfortunately' in chatgpt_result:
                chatgpt_result = 'FAILED'
        except:
            chatgpt_result = 'FAILED'
        with open('results.csv', 'a') as f:
            f.write(f'{message_to_execute}\n{question}')
            f.write(f'{llama_result},{deepseek_result},{starcoder_result},{gemma_result},{chatgpt_result}\n')
        try:
            model = LocalLLM(api_base="http://localhost:11434/v1", model="llama3.1:latest")
            llama_result = local_llm_result(model,question,df)
            if 'Unfortunately' in llama_result:
                llama_result = 'FAILED'
        except:
            llama_result = 'FAILED'
        try:
            model = LocalLLM(api_base="http://localhost:11434/v1", model="deepseek-coder-v2:latest")
            deepseek_result = local_llm_result(model,question,df)
            if 'Unfortunately' in deepseek_result:
                deepseek_result = 'FAILED'
        except:
            deepseek_result = 'FAILED'
        try:
            model = LocalLLM(api_base="http://localhost:11434/v1", model="starcoder2:latest")
            starcoder_result = local_llm_result(model,question,df)
            if 'Unfortunately' in starcoder_result:
                starcoder_result = 'FAILED'
        except:
            starcoder_result = 'FAILED'
        try:
            model = LocalLLM(api_base="http://localhost:11434/v1", model="gemma2:27b")
            gemma_result = local_llm_result(model,question,df)
            if 'Unfortunately' in gemma_result:
                gemma_result = 'FAILED'
        except:
            gemma_result = 'FAILED'
        try:
            chatgpt_result = openai_result(question,df)
            if 'Unfortunately' in chatgpt_result:
                chatgpt_result = 'FAILED'
        except:
            chatgpt_result = 'FAILED'
        with open('results.csv', 'a') as f:
            f.write(f'{llama_result},{deepseek_result},{starcoder_result},{gemma_result},{chatgpt_result},{str(c//10)}\n')
            f.write('\n')
        ### End of factory

        
        

        